package ru.stepuk.modern;

import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.ScalingControl;
import java.awt.geom.Point2D;
import java.util.Iterator;
import ru.stepuk.modern.nodes.Node;
import ru.stepuk.modern.events.StopSimulation;
import ru.stepuk.modern.nodes.Source;

/**
 *
 * @author ivan
 */
public class Controller {

    private Model model;
    private Timeline timeline;
    private Node.NodeType nodeToPlace;
    private ScalingControl scaler;
    private boolean autoAlign = false;
    public static final int GRID_SIZE = 32;

    public boolean isAutoAlign() {
        return autoAlign;
    }

    public void setAutoAlign(boolean autoAlign) {
        this.autoAlign = autoAlign;
    }

    public Controller(Model model, Timeline timeline, ScalingControl scaler) {
        this.model = model;
        this.timeline = timeline;
        this.scaler = scaler;
    }

    public Node.NodeType getNodeToPlace() {
        return nodeToPlace;
    }

    public void setNodeToPlace(Node.NodeType nodeToPlace) {
        this.nodeToPlace = nodeToPlace;
    }

    public void alignNodes(VisualizationViewer vv) {
        Iterator<Node> iter = model.getAllNodes().iterator();
        while (iter.hasNext()) {
            Node node = iter.next();
            Point2D prev = (Point2D) vv.getGraphLayout().transform(node);
            double dx = prev.getX() % GRID_SIZE;
            double dy = prev.getY() % GRID_SIZE;
            Point2D newLocation = new Point2D.Double(
                    dx < GRID_SIZE / 2 ? prev.getX() - dx : prev.getX() - dx + GRID_SIZE,
                    dy < GRID_SIZE / 2 ? prev.getY() - dy : prev.getY() - dy + GRID_SIZE);
            vv.getGraphLayout().setLocation(node, newLocation);

        }
        vv.repaint();
    }

    public void zoomIn(VisualizationViewer vv) {

        scaler.scale(vv, 1.2f, getCenterOfVisualizer(vv));
    }

    public void zoomOut(VisualizationViewer vv) {

        scaler.scale(vv, 1 / 1.2f, getCenterOfVisualizer(vv));
    }

    private Point2D getCenterOfVisualizer(VisualizationViewer vv) {
        return new Point2D.Double(
                vv.getParent().getBounds().getCenterX(),
                vv.getParent().getBounds().getCenterY());
    }

    public void startSimulation(double period) {
        System.out.println("\n=============================\nSIMULATION STARTED...");
        boolean errors = false;
        boolean limited = false;

        if (period != 0) {
            limited = true;
            timeline.addEvent(period, new StopSimulation(timeline));
        }

        for (Iterator<Node> it = model.getAllNodes().iterator(); it.hasNext();) {

            try {
                it.next().validate();
            } catch (InvalidModelException ex) {
                errors = true;
                System.out.println(ex.toString());
            }
        }


        for (Iterator<Source> it = model.getSources().iterator(); it.hasNext();) {
            Source s = it.next();
            limited |= (s.getPopulation() != 0);
            s.setCreationEvent();
        }

        if (!limited) {
            errors = true;
            System.out.println("No limits");
        }

        if (!errors) {
            timeline.play();
        } else {
            timeline.clear();
        }
    }

    public void newModel(VisualizationViewer vv) {
        model.reset();
        vv.repaint();
    }
}
